package com.coolgor.coldot.web.wechat.gzh;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.coolgor.coldot.common.wechat.HttpUtil;
import com.coolgor.coldot.dto.wechat.gzh.GZHAccessTokenExecution;
import com.coolgor.coldot.dto.wechat.gzh.GZHUserExecution;
import com.coolgor.coldot.dto.wechat.oauth2.OAuth2AccessTokenExecution;
import com.coolgor.coldot.entity.auth.LoginInfo;
import com.coolgor.coldot.entity.wechat.gzh.GZHAccessToken;
import com.coolgor.coldot.entity.wechat.gzh.GZHUser;
import com.coolgor.coldot.entity.wechat.oauth2.OAuth2AccessToken;
import com.coolgor.coldot.enums.auth.LoginStateEnum;
import com.coolgor.coldot.enums.wechat.gzh.GZHAccessTokenOperationStateEnum;
import com.coolgor.coldot.enums.wechat.gzh.GZHUserOperationStateEnum;
import com.coolgor.coldot.enums.wechat.oauth2.OAuth2AccessTokenOperationStateEnum;
import com.coolgor.coldot.service.auth.LoginInfoService;
import com.coolgor.coldot.service.wechat.gzh.GZHAccessTokenService;
import com.coolgor.coldot.service.wechat.gzh.GZHMessageService;
import com.coolgor.coldot.service.wechat.gzh.GZHUserService;
import com.coolgor.coldot.service.wechat.oauth2.OAuth2AccessTokenService;
import com.coolgor.xutil.Net.HttpServletRequestUtil;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * 获取关注公众号之后的微信用户信息的接口，如果在微信浏览器里访问
 * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd7f6c5b8899fba83&redirect_uri=http://o2o.yitiaojieinfo.com/o2o/wechatlogin/logincheck&role_type=1&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
 * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf5124501c044efec&redirect_uri=http://www.lordforce.com/axnut/wechatlogin/logincheck&role_type=1&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
 * https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxef31de7a23359e19&redirect_uri=http://www.lordforce.com/axnut/wxqyhlogin/logincheck&response_type=code&scope=snsapi_base&state=1#wechat_redirect
 * 则这里将会获取到code,之后再可以通过code获取到access_token 进而获取到用户信息
 * 
 * @author CoolGor
 *
 */
@Controller
@RequestMapping("wxfwh")
public class WechatFWHLoginController {

	private static Logger log = LoggerFactory.getLogger(WechatFWHLoginController.class);


	@Autowired
	GZHAccessTokenService gzhAccessTokenService;

	@Autowired
	GZHUserService gzhUserService;

	@Autowired
	GZHMessageService gzhMessageService;

	@Autowired
	OAuth2AccessTokenService oauth2AccessTokenService;

	@Autowired
	LoginInfoService loginInfoService;

	

	@RequestMapping(value="/login", method={RequestMethod.GET}, produces= {"application/json;charset=UTF-8"})
	@ResponseBody
	//@JsonIgnoreProperties(ignoreUnknown = true)//用ObjectMapper转换json对象时，忽略不存在的字段。
	public Map<String, Object> doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		Map<String, Object> modelMap = new HashMap<String, Object>();
		log.debug("WXFWH login get...");

		// 获取微信公众号传输过来的code,通过code可获取access_token,进而获取用户信息
		String code = request.getParameter("code");
		if (null==code || "".equals(code)) {
			modelMap.put("success","false");
			modelMap.put("errMsg","code is null");
			return modelMap;
		}

		// 这个state可以用来传我们数据库中约定的record ID
		String state = request.getParameter("state");
		String[] states = state.split("_");
		String recordID = states[0];
		if (null==recordID || "".equals(recordID)) {
			modelMap.put("success","false");
			modelMap.put("errMsg","RecordID is null");
			return modelMap;
		}

		// 根据recordID从数据库中获取记录
		GZHAccessTokenExecution gzhAccessTokenExecution = gzhAccessTokenService.getGZHAccessToken(Long.parseLong(recordID));
		if (gzhAccessTokenExecution.getState() != GZHAccessTokenOperationStateEnum.SUCCESS.getState()) {
			modelMap.put("success","false");
			modelMap.put("errMsg","从数据库中获取BaseAccessToken时出错：" + gzhAccessTokenExecution.getStateInfo());
			return modelMap;
		}

		GZHAccessToken gzhAccessToken = gzhAccessTokenExecution.getGZHAccessToken();
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
				+ gzhAccessToken.getAppID()
				+ "&secret=" + gzhAccessToken.getSecret()
				+ "&code=" + code
				+ "&grant_type=authorization_code";

		String resStr = HttpUtil.httpsRequest(url, "GET", null);
		ObjectMapper objectMapper = new ObjectMapper();
		Map<String, Object> resMap = null;
		try {
			// 将json字符串转换成相应对象
			resMap = objectMapper.readValue(resStr, Map.class);
		} catch (JsonParseException e) {
			log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
			e.printStackTrace();
		} catch (JsonMappingException e) {
			log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			log.error("从腾讯服务器中获取accessToken失败: " + e.getMessage());
			e.printStackTrace();
		}

		// 解析返回结果
		if ( null == resMap	|| null!=resMap.get("errcode") ) {
			log.error("获取网页授权accessToken失败。");
			modelMap.put("success","false");
			modelMap.put("errMsg","获取网页授权accessToken失败。" );
			return modelMap;
		}
		OAuth2AccessToken oauth2AccessToken = new OAuth2AccessToken();
		oauth2AccessToken.setAppID(gzhAccessToken.getAppID());
		oauth2AccessToken.setAppName(gzhAccessToken.getAppName());
		oauth2AccessToken.setAccessToken((String) resMap.get("access_token"));
		oauth2AccessToken.setAccessTokenCreateTime(new Date(System.currentTimeMillis()-100*1000));
		oauth2AccessToken.setAccessTokenInvalidTime(new Date(System.currentTimeMillis()-100*1000+gzhAccessToken.getExpireTime()*1000));
		oauth2AccessToken.setAccessTokenExpireTime((int) resMap.get("expires_in"));
		oauth2AccessToken.setRefreshToken((String) resMap.get("refresh_token"));
		oauth2AccessToken.setRefreshTokenCreateTime(new Date(System.currentTimeMillis()-100*1000));
		oauth2AccessToken.setOpenid((String) resMap.get("openid"));
		oauth2AccessToken.setScope((String) resMap.get("scope"));
		// OAuth2AccessTokenExecution 执行插入更新操作
		OAuth2AccessTokenExecution oauth2AccessTokenExecution = oauth2AccessTokenService.uptodate(oauth2AccessToken);
		if (oauth2AccessTokenExecution.getState() != OAuth2AccessTokenOperationStateEnum.SUCCESS.getState()){
			log.error("在数据库中uptodate公众号的网页授权accessToken失败。");
			modelMap.put("success","false");
			modelMap.put("errMsg","在数据库中插入公众号的网页授权accessToken失败。" );
			return modelMap;
		}


		url = "https://api.weixin.qq.com/sns/userinfo"
				+ "?access_token=" + oauth2AccessToken.getAccessToken()
				+ "&openid=" + oauth2AccessToken.getOpenid()
				+ "&lang=zh_CN";
		resStr = HttpUtil.httpsRequest(url, "GET", null);
		objectMapper = new ObjectMapper();
		resMap = null;
		try {
			// 将json字符串转换成相应对象
			resMap = objectMapper.readValue(resStr, Map.class);
		} catch (JsonParseException e) {
			log.error("从腾讯服务器中获取userinfo失败: " + e.getMessage());
			e.printStackTrace();
		} catch (JsonMappingException e) {
			log.error("从腾讯服务器中获取userinfo失败: " + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			log.error("从腾讯服务器中获取userinfo失败: " + e.getMessage());
			e.printStackTrace();
		}

		// 解析返回结果
		if ( null == resMap	|| null!=resMap.get("errcode") ) {
			log.error("获取网页授权accessToken失败。");
			modelMap.put("success","false");
			modelMap.put("errMsg","从腾讯服务器中获取userinfo失败。" );
			return modelMap;
		}
		// 配置GZHUser信息
		GZHUser gzhUser = new GZHUser();
		gzhUser.setAppID(oauth2AccessToken.getAppID());
		gzhUser.setOpenid((String) resMap.get("openid"));
		gzhUser.setUnionid((String) resMap.get("unionid"));
		gzhUser.setNickname((String) resMap.get("nickname"));
		gzhUser.setSex((int) resMap.get("sex"));
		gzhUser.setCountry((String) resMap.get("country"));
		gzhUser.setProvince((String) resMap.get("province"));
		gzhUser.setCity((String) resMap.get("city"));
		gzhUser.setHeadimgurl((String) resMap.get("headimgurl"));
		gzhUser.setPrivilege(((List) resMap.get("privilege")).toString());

		// GZHUser 执行插入更新操作
		GZHUserExecution gzhUserExecution = gzhUserService.uptodate(gzhUser);
		if (gzhUserExecution.getState() != GZHUserOperationStateEnum.SUCCESS.getState()){
			log.error("在数据库中uptodate公众号的用户信息失败。");
			modelMap.put("success","false");
			modelMap.put("errMsg","在数据库中uptodate公众号的用户信息失败。" );
			return modelMap;
		}


		//制作登录日志信息
		LoginInfo loginInfo = new LoginInfo();
		loginInfo.setUserID(gzhUser.getRecordID());
		loginInfo.setUsername(gzhUser.getOpenid());
		loginInfo.setNameCN(gzhUser.getNickname());
		loginInfo.setLoginRoleId(999L);
		loginInfo.setLoginRoleName("公众号登录用户");
		loginInfo.setLoginIP(HttpServletRequestUtil.getIP(request));
		loginInfo.setLoginWay(LoginStateEnum.WECHAT_FWH.getStateInfo());
		loginInfo.setRemark(gzhAccessToken.getAppName());
		//将本次登录日志写入数据库中
		loginInfoService.addLoginInfo(loginInfo);

		gzhMessageService.sendTemplateMessage(Long.parseLong(recordID),
				"登录成功提醒",
				"oQj0it9tozdjZfwUKsZjkp4WLQJ8",
				"测试|测试");

		gzhMessageService.sendTemplateMessage(gzhAccessToken.getAppID(),
				"工作任务提醒",
				"oQj0it9tozdjZfwUKsZjkp4WLQJ8",
				null,
				"这里是主要的信息这里是\n主要的信息这里是主要的信息这里是主\n要的信息这里是主要的信息这里是\n主要的信息这里是主要的信息",
				null,
				"http://www.baidu.com");


		modelMap.put("success","true");
		modelMap.put("AppID", oauth2AccessToken.getAppID());
		modelMap.put("唯一标识", (String) resMap.get("openid"));
		modelMap.put("昵称", (String) resMap.get("nickname"));
		modelMap.put("性别", (int) resMap.get("sex")); //性别必须是int类型，值为1时是男性，值为2时是女性，值为0时是未知
		modelMap.put("省份", (String) resMap.get("province"));
		modelMap.put("城市", (String) resMap.get("city"));
		modelMap.put("国家", (String) resMap.get("country"));
		modelMap.put("用户头像", (String) resMap.get("headimgurl"));
		modelMap.put("用户特权信息", (List) resMap.get("privilege"));//用户特权信息必须是List类型
		modelMap.put("unionid", (String) resMap.get("unionid"));

		return modelMap;
	}
	
	
	
}
